package org.example.trigger.http;


import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.example.domain.activity.model.entity.ActivityAccountDayEntity;
import org.example.domain.activity.service.IActivityAccountQuota;
import org.example.domain.strategy.model.Raffle.RaffleAwardEntity;
import org.example.domain.strategy.model.Raffle.RaffleFactorEntity;
import org.example.domain.strategy.model.Raffle.StrategyAwardEntity;
import org.example.domain.strategy.model.valobj.RuleWeightVO;
import org.example.domain.strategy.service.IRaffleRule;
import org.example.domain.strategy.service.IRaffleStrategy;
import org.example.domain.strategy.service.armory.IStrategyArmory;
import org.example.domain.strategy.service.armory.IStrategyDispatch;
import org.example.trigger.api.IRaffleStrategyService;
import org.example.trigger.api.dto.*;
import org.example.types.enums.ResponseCode;
import org.example.types.exception.AppException;
import org.example.types.model.Response;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Slf4j
@CrossOrigin("${app.config.cross-origin}")
@RestController()
@RequestMapping("/api/${app.config.api-version}/raffle/strategy")
public class RaffleStrategyController implements IRaffleStrategyService {

    @Resource
    private IRaffleStrategy raffleStrategy;

    @Resource
    private IStrategyArmory strategyArmory;

    @Resource
    private IStrategyDispatch strategyDispatch;

    @Resource
    private IRaffleRule raffleRule;

    @Resource
    private IActivityAccountQuota raffleActivityAccountQuota;

    @RequestMapping(value = "strategy_armory", method = RequestMethod.GET)
    public Response<Boolean> strategyArmory(@RequestParam Long strategyId){

        try {
            boolean status = strategyArmory.assembleLotteryStrategy(strategyId);
            log.info("装配成功");
            return Response.<Boolean>builder()
                    .code(ResponseCode.SUCCESS.getCode())
                    .info(ResponseCode.SUCCESS.getInfo())
                    .data(status)
                    .build();
        }catch(Exception e){
            return Response.<Boolean>builder()
                    .code(ResponseCode.UN_ERROR.getCode())
                    .info(ResponseCode.UN_ERROR.getInfo())
                    .build();
        }
    }


    /**
     * 返回对应strategyId的奖品信息
     * 返回对应useId的奖品解锁信息
     * @param raffleAwardListRequestDTO 抽奖奖品列表查询请求参数
     * @return 返回信息
     */
    @RequestMapping(value="query_raffle_award_list",method = RequestMethod.POST)
    public Response<List<RaffleAwardListResponseDTO>> queryRaffleAwardList(@RequestBody RaffleAwardListRequestDTO raffleAwardListRequestDTO){

        try {
            //1.参数校验

            //2.查出奖品基本信息
            List<RaffleAwardListResponseDTO> raffleAwardListResponseDTOList = new ArrayList<>();
            List<StrategyAwardEntity> strategyAwardEntities = strategyDispatch.getAwardEntityListByActivityId(raffleAwardListRequestDTO.getActivityId());

            //找出所有奖品对应的规则树的id,再统一找到对应规则树id所对应的rule-lock规则值,即次数锁的值,再复制到返回实体中
            String[] treeIds = strategyAwardEntities.stream()
                    .map(StrategyAwardEntity::getRuleModels)
                    .filter(ruleModel -> StringUtils.isNotBlank(ruleModel))
                    .distinct()
                    .toArray(String[]::new);

            Map<String , Integer> map  = raffleRule.queryRuleLockValue(treeIds);
            //获取当前日期day
            Date currentDate =new Date();
            SimpleDateFormat dateFormatDay = new SimpleDateFormat("yyyy-MM-dd");
            String day = dateFormatDay.format(currentDate);

            //查询今天的抽奖次数
            ActivityAccountDayEntity activityAccountDayEntity = raffleActivityAccountQuota.queryRaffleActivityAccountDay(raffleAwardListRequestDTO.getActivityId(), raffleAwardListRequestDTO.getUserId(),day);
            Integer raffleCount = activityAccountDayEntity.getDayCount()-activityAccountDayEntity.getDayCountSurplus();

            for (StrategyAwardEntity strategyAwardEntity : strategyAwardEntities) {
               Integer raffleRuleCount =  map.get(strategyAwardEntity.getRuleModels());
                RaffleAwardListResponseDTO raffleAwardListResponseDTO = RaffleAwardListResponseDTO.builder()
                        .awardId(strategyAwardEntity.getAwardId())
                        .awardTitle(strategyAwardEntity.getAwardTitle())
                        .awardSubtitle(strategyAwardEntity.getAwardSubtitle())
                        .sort(strategyAwardEntity.getSort())
                        .awardRuleLockCount(raffleRuleCount)
                        .isAwardUnlock(null == raffleRuleCount ||raffleCount>=raffleRuleCount)//raffleRuleCount为null说明该奖品未配置次数规则
                        .waitUnLockCount(null == raffleRuleCount ||raffleCount>=raffleRuleCount?0:(raffleRuleCount-raffleCount))
                        .build();

                raffleAwardListResponseDTOList.add(raffleAwardListResponseDTO);
            }

            return Response.<List<RaffleAwardListResponseDTO>>builder()
                    .code(ResponseCode.SUCCESS.getCode())
                    .info(ResponseCode.SUCCESS.getInfo())
                    .data(raffleAwardListResponseDTOList)
                    .build();
        }catch(Exception e){
            return Response.<List<RaffleAwardListResponseDTO>>builder()
                    .code(ResponseCode.UN_ERROR.getCode())
                    .info(ResponseCode.UN_ERROR.getInfo())
                    .build();
        }
    }



    @RequestMapping(value = "random_raffle", method = RequestMethod.POST)
    public Response<RaffleStrategyResponseDTO> randomRaffle(@RequestBody RaffleStrategyRequestDTO requestDTO) {
        try {
            RaffleAwardEntity raffleAwardEntity = raffleStrategy.performRaffle(RaffleFactorEntity.builder()
                    .strategyId(requestDTO.getStrategyId())
                    .userId("xiaofuge")
                    .build());

            RaffleStrategyResponseDTO raffleStrategyResponseDTO = RaffleStrategyResponseDTO.builder()
                    .awardId(Integer.valueOf(raffleAwardEntity.getAwardId()))
                    .awardIndex(Integer.valueOf(raffleAwardEntity.getSort()))
                    .build();

            log.info("随机抽奖完成 strategyId: {}", requestDTO.getStrategyId());
            return Response.<RaffleStrategyResponseDTO>builder()
                    .code(ResponseCode.SUCCESS.getCode())
                    .info(ResponseCode.SUCCESS.getInfo())
                    .data(raffleStrategyResponseDTO)
                    .build();

        } catch (AppException e) {
            log.info("发生runtime错误");
            return Response.<RaffleStrategyResponseDTO>builder()
                    .code(ResponseCode.UN_ERROR.getCode())
                    .info(ResponseCode.UN_ERROR.getInfo())
                    .build();
        }catch (Exception e) {
            log.info("发生错误");
            return Response.<RaffleStrategyResponseDTO>builder()
                    .code(ResponseCode.UN_ERROR.getCode())
                    .info(ResponseCode.UN_ERROR.getInfo())
                    .build();
        }
    }

    /**
     * 查询抽奖次数门槛及其对应奖品范围 请求
     * @param request
     * @return 门槛及其返回值列表(包含用户抽奖次数)
     */
    @Override
    public Response<List<RaffleStrategyRuleWeightResponseDTO>> queryRaffleStrategyRuleWeight(RaffleStrategyRuleWeightRequestDTO request) {
//        try {
            Long activityId = request.getActivityId();
            String userId = request.getUserId();

            if (activityId ==null && StringUtils.isBlank(userId)){
                throw new AppException(ResponseCode.ILLEGAL_PARAMETER.getCode(),ResponseCode.ILLEGAL_PARAMETER.getInfo());
            }
            //查询用户已抽奖次数
            Integer userActivityAccountTotalUseCount = raffleActivityAccountQuota.queryRaffleActivityAccountPartakeCount(request.getActivityId(), request.getUserId());

            List<RaffleStrategyRuleWeightResponseDTO> raffleStrategyRuleWeightResponseDTOS = new ArrayList<>();
            //用VO对象去接收想要查出的权重展示的值
            List<RuleWeightVO> ruleWeightVOS = raffleRule.queryAwardRuleWeightByActivityId(activityId);
            //再转化成DTO传给前台
            for (RuleWeightVO  ruleWeightVO: ruleWeightVOS){
                RaffleStrategyRuleWeightResponseDTO raffleStrategyRuleWeightResponseDTO =new RaffleStrategyRuleWeightResponseDTO();
                //1.用户抽奖次数
                raffleStrategyRuleWeightResponseDTO.setUserActivityAccountTotalUseCount(userActivityAccountTotalUseCount);
                //2.规则权重值
                raffleStrategyRuleWeightResponseDTO.setRuleWeightCount(ruleWeightVO.getWeight());
                //3.涉及的奖品信息
                List<RaffleStrategyRuleWeightResponseDTO.StrategyAward> strategyAwards = new ArrayList<>();
                for (RuleWeightVO.Award award :ruleWeightVO.getAwardList()){
                    RaffleStrategyRuleWeightResponseDTO.StrategyAward strategyAward = new RaffleStrategyRuleWeightResponseDTO.StrategyAward();
                    strategyAward.setAwardId(award.getAwardId());
                    strategyAward.setAwardTitle(award.getAwardTitle());
                    strategyAwards.add(strategyAward);
                }
                raffleStrategyRuleWeightResponseDTO.setStrategyAwards(strategyAwards);

                raffleStrategyRuleWeightResponseDTOS.add(raffleStrategyRuleWeightResponseDTO);
            }


            return Response.<List<RaffleStrategyRuleWeightResponseDTO>>builder()
                    .code(ResponseCode.SUCCESS.getCode())
                    .info(ResponseCode.SUCCESS.getInfo())
                    .data(raffleStrategyRuleWeightResponseDTOS)
                    .build();
//        } catch (AppException e) {
//            log.info("发送自定义错误");
//            return Response.<List<RaffleStrategyRuleWeightResponseDTO>>builder()
//                    .code(e.getCode())
//                    .info(e.getInfo())
//                    .build();
//        }catch (Exception e){
//            log.info("发送未知错误");
//            return Response.<List<RaffleStrategyRuleWeightResponseDTO>>builder()
//                    .code(ResponseCode.UN_ERROR.getCode())
//                    .info(ResponseCode.UN_ERROR.getInfo())
//                    .build();
//        }

    }


}
